﻿using System;
using System.Linq;
using System.Data;
using System.Text.RegularExpressions;
using System.Windows.Forms;
using System.Diagnostics;
using System.Threading;
using System.ComponentModel;
using System.Text;
using System.IO;
using DGen;
using Tab2Sql.Classes;
using Tab2Sql.Classes.Core;
using Tab2Sql.Classes.Convertors;
using Tab2Sql.Classes.db;
namespace Tab2Sql
{
    /// <summary>
    /// Main.
    /// </summary>
    partial class MainForm
    {
        // PRIVATE METHODS

        /*---------------------------------------------------------------------------------------------------------------------------------------------
         *  CORE METHODS 
         *  These are methods/routines/stuff required to actually get things to work.
         * ---------------------------------------------------------------------------------------------------------------------------------------------*/
        private void Reset ()
        {
        	logger.Trace ("Reset Called.");
			if (history != null)
            {
                history = null;
            }
            history = new historyDB();

            if (swatch == null)
            {
                swatch = new Stopwatch();
            }
            swatch.Reset();
            boxChosenTableName.Text = MyOptions.TableName;
            inStr.Clear();
            inStr.ClearUndo();
            outStr.Clear();
            outStr.ClearUndo();
            lblStatus.Text = "";
            lblTopRows.Visible = false;
            boxSeparator.Text = MyOptions.Delimiter;
            if (boxSeparator.Text == "\t") { boxSeparator.Text = "\\t"; }
            if (boxSeparator.TextLength == 0) { boxSeparator.Text = Properties.Settings.Default.Delimiter; }
            boxStatus.Clear();
            boxStatus.AppendText(string.Format("Reset @ {0} \nDelimiter: {1}", DateTime.Now, MyOptions.Delimiter));
            Global.generatedSQL = null;
            pivotButton.Enabled = false;
            ourDataTable = null;
            GC.Collect();
        }
        private int showStatusMsgs()
        {
            swatch.Stop();
            reCount();
            int returnValue = 0;
            lblStatus.Text = swatch.ElapsedMilliseconds.ToString() + " ms.";

            return returnValue;
        }
        private int LaunchConversion()
        {
            otherLaunch();
            return 0;
        }
        private void setOptions()
        {

            MyOptions.ColumnNameModel = HandlingOfColumnNames.Standard;

            if (multiInsert.Checked == true)
            {
                MyOptions.StatementType = SqlStatementType.MultiInsert;
            }
            if (singleInsert.Checked == true)
            {
                MyOptions.StatementType = SqlStatementType.Standard;
            }


            if (includeRowNumber.Checked == false)
            {
                MyOptions.IncludeRowNumber = RowID.None;
            }
            else
            {
                MyOptions.IncludeRowNumber = RowID.AddRowNumber;
            }
            MyOptions.Delimiter = boxSeparator.Text;

            MyOptions.TableName = boxChosenTableName.Text;
            MyOptions.FirstRowIsHeader = cbUseFirstRowAsHeader.Checked;
            //if (cbAddCol1.Checked == true)
            //{
            //    MyOptions.AddCol1Name = boxAddCol1.Text;
            //    MyOptions.AddCol1DataType = lstAddCol1.SelectedItem.ToString();
            //}


        }
        /*---------------------------------------------------------------------------------------------------------------------------------------------
         *  FILES / IO RELATED
         *  Loading, saving, etc. 
         * ---------------------------------------------------------------------------------------------------------------------------------------------*/
        private void loadFileBox_FileOk(object sender, CancelEventArgs e)
        {
            if (loadFileBox.FileName.ToUpper().EndsWith("SQLITE"))
            {
                doInternalDB(loadFileBox.FileName);
            }
            else
            {
                LoadFile LFile = new LoadFile(loadFileBox.FileName, ref inStr);
                if (LFile.LargeFileMode == true) { largeFileMode = true; }
                realLineCount = LFile.LineCount;
                boxStatus.Text += inStr.ImportedFileName;
                boxStatus.Text += Environment.NewLine + inStr.Mseconds;
                reCount();
            }
        }

        private void doInternalDB(string p)
        {
            theInternalDB = new internalDB(true,p);
            boxStatus.AppendText("Done.");
        }
        private string GetFolderName()
        {
            string pathName;
            if (Directory.Exists(inStr.SelectedText))
            {
                pathName = inStr.SelectedText;
            }
            else
            {
                folderBrowserDialog1.ShowDialog();
                pathName = folderBrowserDialog1.SelectedPath;
            }
            return pathName;
        }
        private void doLoadFile (string fileType)
        {
            loadFileBox.Title = "Load Input File...";
            loadFileBox.FileOk += new CancelEventHandler (loadFileBox_FileOk);
            loadFileBox.DefaultExt = fileType;
            loadFileBox.FileName = "*." + fileType;

            loadFileBox.Filter = @"All files (*.*)|*.*" +
                                 @"|Text files (*.txt)|*.txt" +

                                 @"|csv Files (*.csv)|*.csv" +
                                 @"|tsv Files (*.tsv)|*.tsv" +
                                 @"|log Files (*.log)|*.log" +
                                 @"|xls Files (*.xls)|*.xls;"+
                                 @"|sqlite Files (*.sqlite)|*.sqlite;"; ;
            loadFileBox.ShowDialog();
        }
        private void doLoadFile()
        {
            doLoadFile("*");
        }
        private void doSave()
        {

            saveFileDialog1.DefaultExt = ".sql";
            saveFileDialog1.AutoUpgradeEnabled = true;
            saveFileDialog1.AddExtension = true;
            saveFileDialog1.FileName = MyOptions.TableName.Replace("#", "") + ".sql";
            saveFileDialog1.ShowDialog();
        }
        private string doQuickSave()
        {
            string responseMessage = "";

            if (outStr.TextLength > 50)
            {
                int xVersion = 1;
                string fname = "t2s" + xVersion.ToString() + ".sql";
                while (File.Exists(fname) == true)
                {
                    fname = "t2s" + xVersion.ToString() + ".sql";
                    xVersion++;
                }

                try
                {
                    string txt = sqlFragments.getPreamble() + Environment.NewLine + outStr.Text;
                    string size = "";
                    string fullPath = "";
                    DGen.DFile.WriteToFile(fname, txt, true);
                    if (File.Exists(fname))
                    {
                        FileInfo finfo = new FileInfo(fname);
                        size = DGen.DText.FormatBytes(finfo.Length);
                        fullPath = finfo.FullName;
                        finfo = null;
                    }
                    responseMessage = fullPath + "\n" + size;
                }
                catch (Exception ex)
                {
                    responseMessage = "FAIL - " + ex.Message;
                }

            }
            return responseMessage;
        }
        /*---------------------------------------------------------------------------------------------------------------------------------------------
         *  INPUT MANGLERS
         *  
         * ---------------------------------------------------------------------------------------------------------------------------------------------*/
        /// <summary>
        /// Detetect delimiter from block of text;
        /// </summary>
        /// <returns></returns>
        private string delimiterScan (string[] inLines)
        {

            string d = MyOptions.Delimiter;
            if (boxSeparator.Text != d && (boxSeparator.Text == @"\|" || boxSeparator.Text == "\t" || boxSeparator.Text == "," || boxSeparator.Text == "-" || boxSeparator.Text == "|"))
            {
                d = boxSeparator.Text;
                if (d == @"\|")
                {
                    d = @"|";
                }
            }
            //return Delimiter.DelimiterScan(ref inLines, d,0);
            Delimiter delimiter = new Delimiter ();
            return delimiter.DelimiterScan (ref inLines, d, true);

        }
        private string getDTSummary(bool showColumnList)
        {

            StringBuilder sb = new StringBuilder();
            sb.AppendLine(ourDataTable.Rows.Count.ToString() + " rows.");
            sb.AppendLine(ourDataTable.Columns.Count.ToString() + " columns.");
            if (showColumnList == true)
            {
                foreach (DataColumn dc in ourDataTable.Columns)
                {
                    sb.AppendLine(dc.ColumnName + " - " + dc.DataType);

                }
            }

            return sb.ToString();

        }
        private void RemoveCustom()
        {
            int lengthBefore = inStr.Text.Length;
            if (lengthBefore > 0)
            {
                string moo = "";
                Tab2Sql.Forms.CustomReplace cr = new Tab2Sql.Forms.CustomReplace(ref moo);
                cr.Activate();
                cr.ShowDialog();
                string foo = cr.SearchPattern;
                cr.RemoteClose();
                inStr.Text = InputAdjustment.GetRidOf(foo, inStr.Text,true);

                int lengthAfter = inStr.Text.Length;
                int charsRemoved = lengthBefore - lengthAfter;
                boxStatus.Text += charsRemoved.ToString() + " chars removed.";
            }
        }

      
        private void FilterByDelimiter()
        {
            int magicNumber = 0;
            int nbrLines = inStr.Lines.Count();
            int[] myDCount = new int[nbrLines];
            dialogBoxDelimiterQuery myDialog = new dialogBoxDelimiterQuery(this);
            myDialog.Activate();
            myDialog.ShowDialog();
            dialogBoxDelimiterQuery.Criteria dCriteria = myDialog.DelimiterCriteria;
            magicNumber = myDialog.DelimiterCount;
            myDialog.RemoteClose();
            int yCount = 0;
            string tmp = "";
            for (int i = 0; i < nbrLines; i++)
            {
                int y = DGen.DText.CountOccurences(MyOptions.Delimiter, inStr.Lines[i]);
                tmp += "\n" + i.ToString() + "-->" + y.ToString() + "-->" + MyOptions.Delimiter;
                myDCount[i] = y;
                switch (dCriteria)
                {
                    case dialogBoxDelimiterQuery.Criteria.Exactly:
                        if (y == magicNumber) { yCount++; }
                        break;
                    case dialogBoxDelimiterQuery.Criteria.MoreThan:
                        if (y > magicNumber) { yCount++; }
                        break;
                    case dialogBoxDelimiterQuery.Criteria.LessThan:
                        if (y < magicNumber) { yCount++; }
                        break;
                    default:
                        break;
                }
            }
            string[] postFilter = new string[yCount];
            int x = 0;
            for (int i = 0; i < nbrLines; i++)
            {
                switch (dCriteria)
                {
                    case dialogBoxDelimiterQuery.Criteria.Exactly:
                        if (myDCount[i] == magicNumber)
                        {
                            postFilter[x] = inStr.Lines[i];
                            x++;
                        }
                        break;
                    case dialogBoxDelimiterQuery.Criteria.MoreThan:
                        if (myDCount[i] > magicNumber)
                        {
                            postFilter[x] = inStr.Lines[i];
                            x++;
                        }
                        break;
                    case dialogBoxDelimiterQuery.Criteria.LessThan:
                        if (myDCount[i] < magicNumber)
                        {
                            postFilter[x] = inStr.Lines[i];
                            x++;
                        }
                        break;
                    default:
                        break;
                }
            }
            inStr.Lines = postFilter;
        }
        /*---------------------------------------------------------------------------------------------------------------------------------------------
         *  OUTPUT MANGLERS
         *  
         * ---------------------------------------------------------------------------------------------------------------------------------------------*/        
        private void startPivot ()
        {
   
			try 
			{
        		if (mts != null)
				{
        			Pivot pv = new Pivot (mts.OurDataTable);
        			
        			pv.DoPivot ();
        			ourDataTable = null;
        			ourDataTable = pv.EndDT;
        			pv = null;
        			if (ourDataTable != null)
					{
        				var xts = DGen.DText.ObjectToString.DataTableToString (ourDataTable);
        				outStr.Text = xts;
      
        				//dtHelper dth = new dtHelper (ourDataTable);
        				//TODO : Erm...some code here plz.
						

				}
				}
        	}
			catch (Exception ex)
			{
        		logger.Error (ex.Message);
        		MessageBox.Show (ex.Message);
        	}
        }
		
        private void quickDiag()
        {
           
            NavelGazing nvg = new NavelGazing();
            string moo = nvg.ProgramBlurb;
             boxStatus.AppendText(moo);
        }
        private void formatSql ()
        {
			/*
			 * NOT IMPLEMENTED IN MONO
			 */
            RichTextBox rtb = new RichTextBox();
			//inStr.Text;
            outStr.Rtf = rtb.Rtf;
       
            rtb = null;
        }
        private void outReplaceLiteralNullWithNulls(object sender, EventArgs e)
        {
            outStr.Text = outputAdjustment.ReplaceLiteralNullsWithNulls(outStr.Text);
        }
        private void outReplaceZeroWithNull (object sender, EventArgs e)
        {
            outStr.Text = outputAdjustment.ReplaceZeroWithNulls (outStr.Text);
        }
        /// <summary>
        /// Puts 'Response.Write( )' around each line. For converting blocks of 
        /// HTML to (Classic) ASP/VBScript
        /// </summary>
        private void outResponseWritePrefix(object sender, EventArgs e)
        {

            outStr.Text = outputAdjustment.prefixCode(inStr.Lines);
        }
        private void replaceNULLWithNULLToolStripMenuItem_Click_1(object sender, EventArgs e)
        {
            outStr.Text = outputAdjustment.ReplaceLiteralNullsWithNulls(outStr.Text);
        }
        private void zero2null_Click(object sender, EventArgs e)
        {
            outStr.Text = outputAdjustment.ReplaceZeroWithNulls(outStr.Text);
        }
        /*---------------------------------------------------------------------------------------------------------------------------------------------
        *  DELIMITER RELATED
        *  
        * ---------------------------------------------------------------------------------------------------------------------------------------------*/
        private bool delimiterDetectionHasOccurred = false;
        private string detectedDelimiter;
        private int detectedTextLength = 0;
        private string autoDelimiter
        {
            get
            {
                // Have we already done this.
                if (delimiterDetectionHasOccurred == true && inStr.TextLength == detectedTextLength)
                {
                    return detectedDelimiter;
                }
                string endDelimiter = MyOptions.Delimiter;
                try
                {
                    PrepareText pText = new PrepareText(inStr.Text, MyOptions.Delimiter, MyOptions.AutoDetectDelimiterRowLimit);
                    endDelimiter = pText.Delimiter;

                    pText = null;
                }
                catch (Exception ex)
                {
                    boxStatus.Text += ex.Message;
                }
                delimiterDetectionHasOccurred = true;
                detectedDelimiter = endDelimiter;
                detectedTextLength = inStr.TextLength;
                return endDelimiter;
            }
        }
        private string detect(string p, string q)
        {
            // Have we already done this.
            if (delimiterDetectionHasOccurred == true && p.Trim().Length == detectedTextLength)
            {
                return detectedDelimiter;
            }
            string endDelimiter = q;
            try
            {
                PrepareText pText = new PrepareText(p, q, MyOptions.AutoDetectDelimiterRowLimit);
                endDelimiter = pText.Delimiter;

                pText = null;
            }
            catch (Exception ex)
            {
                boxStatus.Text += ex.Message;
            }
            delimiterDetectionHasOccurred = true;
            detectedDelimiter = endDelimiter;
            detectedTextLength = p.Trim().Length;
            return endDelimiter;
        }
        /*---------------------------------------------------------------------------------------------------------------------------------------------
         *  BACKGROUND PROCESS RELATED
         *  
         * ---------------------------------------------------------------------------------------------------------------------------------------------*/        
        private void backgroundWorker1_DoWork(object sender, System.ComponentModel.DoWorkEventArgs e,bool something)
        {

            string fileName = e.Argument.ToString();
            string s = String.Empty;
            int NumberOfUpdates = 5;

            long fileSize = 0;
            StringBuilder endS = new StringBuilder();

            try
            {
                using (FileStream fileStream = new FileStream(fileName, FileMode.Open, FileAccess.Read))
                {
                    fileSize = fileStream.Length;
                    int ChunkSize = Convert.ToInt32(fileSize) / NumberOfUpdates;
                    char[] buffer = new char[fileSize * 2];
                    using (StreamReader sReader = new StreamReader(fileStream, Encoding.GetEncoding(1252)))
                    {
                        int iCount = 0;
                        int iPos = 0;
                        int iProgress = 0;
                        while (!sReader.EndOfStream)
                        {
                            iCount++;
                            iProgress = iCount * (100 / NumberOfUpdates);
                            if (iProgress > 100)
                            {
                                iProgress = 100;
                            }
                            sReader.ReadBlock(buffer, iPos, ChunkSize);
                            backgroundWorker1.ReportProgress(iProgress);
                            iPos = iPos + ChunkSize;
                        }
                        s = new string(buffer); // Create new string passing charBuf into the constructor

                    }

                }
            }


            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
                logger.Error(ex.Message);
				
            }

            this.SetText(s);
        }
        private void backgroundWorker1_ProgressReport(object sender, System.ComponentModel.ProgressChangedEventArgs e)
        {
            
            progressBar1.Value = e.ProgressPercentage;

        }
        private void back(object sender, System.ComponentModel.RunWorkerCompletedEventArgs e)
        {

            progressBar1.Value = 0;

        }
        delegate void SetTextCallback(string text);
        private void SetText(string text)
        {
            // InvokeRequired required compares the thread ID of the
            // calling thread to the thread ID of the creating thread.
            // If these threads are different, it returns true.
            if (this.inStr.InvokeRequired)
            {
                SetTextCallback d = new SetTextCallback(SetText);
                this.Invoke(d, new object[] { text });
            }
            else
            {
                this.inStr.AppendText(text);
                
            }
        }
    }
   


}
